import 'package:equatable/equatable.dart';
import 'package:flutter_soundmagus/widget/eq/eq.dart';
import 'package:collection/collection.dart';
import 'package:json_annotation/json_annotation.dart';

part 'advanced_model.g.dart';

@JsonSerializable(explicitToJson: true)
class TimeDelayModel with CmdStringable {
  List<double> timeDelays = List.generate(kChCount, (i) => 0);
  List<int> timeDelayTypes = List.generate(kChCount, (i) => 0);
  TimeDelayModel();

  factory TimeDelayModel.fromJson(Map<String, dynamic> json) =>
      _$TimeDelayModelFromJson(json);

  Map<String, dynamic> toJson() => _$TimeDelayModelToJson(this);

  @override
  String toCmdStr() {
    return timeDelays.mapIndexed((idx, obj) {
      ZFDelayMsg msg = ZFDelayMsg();
      msg.ch.value = idx + 0xc1;
      msg.delay.value = (obj * 100).toInt();
      return '${msg.toHexString()}\n';
    }).join();
  }
}

@JsonSerializable(explicitToJson: true)
class LevelItemModel {
  /// 音量*/
  int volume;

  ///所属音量组
  int volGroup;

  /// 是否静音*/
  bool mute;

  /// 是否倒相*/
  bool paraphase;

  /// 是否链接，链接后只能通过链接选中和取消
  bool linked;

  LevelItemModel(
      {this.volume = 0,
      this.volGroup = 0,
      this.mute = false,
      this.paraphase = false,
      this.linked = false});

  factory LevelItemModel.fromJson(Map<String, dynamic> json) =>
      _$LevelItemModelFromJson(json);

  Map<String, dynamic> toJson() => _$LevelItemModelToJson(this);
}

@JsonSerializable(explicitToJson: true)
class LevelModel extends Equatable with CmdStringable {
  final List<LevelItemModel> items;
  final LevelItemModel totalModel;

  LevelModel({List<LevelItemModel>? items, LevelItemModel? totalModel})
      : this.items = items ?? List.generate(kChCount, (i) => LevelItemModel()),
        this.totalModel = totalModel ?? LevelItemModel();

  LevelItemModel? firstLinkedItemModel() {
    return items.firstWhereOrNull((element) => element.linked);
  }

  factory LevelModel.fromJson(Map<String, dynamic> json) =>
      _$LevelModelFromJson(json);

  Map<String, dynamic> toJson() => _$LevelModelToJson(this);

  @override
  List<Object?> get props => [items, totalModel];

  @override
  String toCmdStr() {
    var str = '';
    str = items.mapIndexed((idx, obj) {
      ZFVolumeMsg msg = ZFVolumeMsg();
      msg.ch.value = idx + 0xc1;
      msg.mute.value = obj.mute ? 1 : 0;
      msg.volume.value = -obj.volume * kVolumeRadio;
      return '${msg.toHexString()}\n';
    }).join();

    //总音量
    ZFTotalVolumeMsg msg = ZFTotalVolumeMsg();
    msg.mute.value = totalModel.mute ? 1 : 0;
    msg.volume.value = -totalModel.volume * kVolumeRadio;
    str += '${msg.toHexString()}\n';

    return str;
  }
}

@JsonSerializable(explicitToJson: true)
class AdvancedModel with CmdStringable {
  TimeDelayModel timeDelay;
  LevelModel level;

  ///通道联调配置
  ChConfig chConfig;

  AdvancedModel(
      {TimeDelayModel? timeDelay, LevelModel? level, ChConfig? chConfig})
      : this.timeDelay = timeDelay ?? TimeDelayModel(),
        this.level = level ?? LevelModel(),
        this.chConfig = chConfig ?? ChConfig();

  LevelItemModel getLevelItem({int? ch}) {
    var i = ch ?? chConfig.selectCh;
    return level.items[i];
  }

  void toggleMute({int ch = 0}) {
    level.items[ch].mute = !level.items[ch].mute;
  }

  void togglePhase({int ch = 0}) {
    level.items[ch].paraphase = !level.items[ch].paraphase;
  }

  ///更新level
  void updateLevel({int? volume, bool? mute, int? volGroup}) {
    if (volGroup != null) {
      // chConfig.toggleChGroup(ch: volGroup);
    }
    if (volume != null) {
      getLevelItem()..volume = volume;
    }
    if (mute != null) {
      getLevelItem()..mute = mute;
    }
  }

  factory AdvancedModel.fromJson(Map<String, dynamic> json) =>
      _$AdvancedModelFromJson(json);

  Map<String, dynamic> toJson() => _$AdvancedModelToJson(this);

  @override
  String toCmdStr() {
    return [timeDelay.toCmdStr(), level.toCmdStr()].join('\n');
  }
}
